home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacWT 0.9 / wt Source / object.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-10  |  5.3 KB  |  246 lines  |  [TEXT/CWIE]

  1. /*
  2. **  MacWT -- a 3d game engine for the Macintosh
  3. **  © 1995, Bill Hayden and Nikol Software
  4. **  Free for non-commercial use - address questions to the e-mail address below
  5. **
  6. **  Mail:           afn28988@freenet.ufl.edu (Bill Hayden)
  7. **    MacWT FTP site: ftp.circa.ufl.edu/pub/software/ufmug/mirrors/LocalSW/Hayden/
  8. **  WWW Page:       http://grove.ufl.edu:80/~nikolsw
  9. **
  10. **    All of the above addresses are due to changes sometime in 1996, so stay tuned
  11. **
  12. **  based on wt, by Chris Laurel
  13. **
  14. **  This program is distributed in the hope that it will be useful,
  15. **  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  17. */
  18.  
  19.  
  20.  
  21. #include <stdlib.h>
  22. #include "wt.h"
  23. #include "error.h"
  24. #include "wtmem.h"
  25. #include "fixed.h"
  26. #include "view.h"
  27. #include "table.h"
  28. #include "list.h"
  29. #include "framebuf.h"
  30. #include "texture.h"
  31. #include "world.h"
  32. #include "object.h"
  33. #include "collision.h"
  34.  
  35.  
  36. #define FP_ZERO(f) (((f) > -1.0e-5) && ((f) < 1.0e-5))
  37.  
  38. double gravity = -0.05;
  39. Bounds    WorldBounds = {0.0, 0.0, 0.0, 0.0};
  40.  
  41.  
  42.  
  43. Object *new_object(double mass, double xsize, double ysize, double height, double drag)
  44. {
  45.     Object *o;
  46.     short    i = MAX_IMAGES;
  47.  
  48.     o = (Object *)wtmalloc(sizeof(Object));
  49.     o->mass = mass;
  50.     o->xsize = xsize;
  51.     o->ysize = ysize;
  52.     o->height = height;
  53.     o->drag = drag;
  54.     
  55.     o->dx = o->dy = o->dz = 0.0;
  56.     o->angle = 0.0;
  57.     o->angular_v = 0.0;
  58.     
  59.     o->region = NULL;
  60.     
  61.     while (i--)
  62.         o->image[i] = NULL;
  63.         
  64.     o->num_images = 0;        // No images yet
  65.     o->cur_image = 0;        // Undefined w/o images
  66.     
  67.     o->frameticks = 0;        // Auto-animate
  68.     o->triggerticks = 0;    
  69.     o->reference = 0;
  70.     
  71.     return o;
  72. }
  73.  
  74.  
  75. void object_update(Object *o)
  76. {
  77.     if (o->drag != 1.0)
  78.         {
  79.         o->dx *= o->drag;
  80.         o->dy *= o->drag;
  81.         o->angular_v *= o->drag;
  82.         }
  83.  
  84.     o->x += o->dx;
  85.     o->y += o->dy;
  86.     o->z += o->dz;
  87.     o->angle += o->angular_v;
  88.     
  89.     // Animate object
  90.     
  91.     if (o->num_images)
  92.         {
  93.         long    secs;
  94.         
  95.         if (!o->frameticks)    // Auto-animate
  96.             AdvanceFrame(o);
  97.         else
  98.             {
  99.             secs = LMGetTicks();
  100.             if (secs >= o->triggerticks)
  101.                 {
  102.                 AdvanceFrame(o);
  103.                 o->triggerticks = secs + o->frameticks;
  104.                 }
  105.             }
  106.         }
  107.         
  108.     // Get the object's region
  109.  
  110.     if (!FP_ZERO(o->dx) || !FP_ZERO(o->dy) || (o->region == NULL))
  111.         o->region = in_region(o->world, FLOAT_TO_FIXED(o->x /*+ (o->dx * o->xsize)*/), FLOAT_TO_FIXED(o->y /*+ (o->dy * o->ysize)*/) );
  112.  
  113.     // Prevent the object from leaving the world entirely
  114.  
  115.     if (o->x < WorldBounds.left + o->xsize)
  116.         o->x = WorldBounds.left + o->xsize;
  117.     else if (o->x > WorldBounds.right - o->xsize)
  118.         o->x = WorldBounds.right - o->xsize;
  119.         
  120.     if (o->y < WorldBounds.top + o->ysize)
  121.         o->y = WorldBounds.top + o->ysize;
  122.     else if (o->y > WorldBounds.bottom - o->ysize)
  123.         o->y = WorldBounds.bottom - o->ysize;
  124.  
  125.  
  126.     // Prevent the object from rising through the ceiling
  127.  
  128.     if (o->z + o->height > FIXED_TO_FLOAT(o->region->ceiling))
  129.         {
  130.         o->z = FIXED_TO_FLOAT(o->region->ceiling) - o->height;
  131.         o->dz = 0.0;
  132.         }
  133.  
  134.  
  135.     // Prevent the object from passing through walls
  136.         
  137.     CheckCollision(o);
  138.     
  139.     
  140.     // Prevent the object from sinking through the floor
  141.  
  142.     if (o->z < FIXED_TO_FLOAT(o->region->floor))
  143.         {
  144.         o->z = FIXED_TO_FLOAT(o->region->floor);
  145.         o->dz = 0.0;
  146.         }
  147.     else
  148.         o->dz += gravity;    // only drop if not already on the floor
  149. }
  150.  
  151.  
  152.  
  153. void object_apply_force(Object *o, double fx, double fy, double fz)
  154. {
  155.     o->dx += fx / o->mass;
  156.     o->dy += fy / o->mass;
  157.     o->dz += fz / o->mass;
  158. }
  159.  
  160.  
  161.  
  162. /* This is a really simple model of torque--since there's no information in
  163. **   the object about mass distribution, there is no moment of inertia.  For
  164. **   lack of something better, we just use the mass.
  165. */
  166. void object_apply_torque(Object *o, double torque)
  167. {
  168.      o->angular_v += torque / o->mass;
  169. }
  170.  
  171.  
  172. /* Set the position of an object in a world--setting an object's position
  173. **   should only be done by calling this function; it should never be
  174. **   set directly by modifying structure fields.
  175. */
  176. extern void object_set_position(Object *o, double x, double y, double z)
  177. {
  178.     if (x != o->x || y != o->y || o->region == NULL)
  179.         o->region = in_region(o->world, FLOAT_TO_FIXED(x), FLOAT_TO_FIXED(y));
  180.         
  181.     o->x = x;
  182.     o->y = y;
  183.     o->z = z;
  184. }
  185.  
  186.  
  187. void add_object(World *w, Object *o)
  188. {
  189.      /* Add an object to a world.  The object is added to the beginning of
  190.      **   the list.  When an object is destroyed, we search for it in the
  191.      **   the list starting from the beginning.  This ends up being quite
  192.      **   efficient since the object being destroyed is likely to have
  193.      **   been created recently.
  194.      */
  195.      add_node(w->objects, o);
  196.      
  197.      o->world = w;
  198. }
  199.  
  200.  
  201. Boolean remove_object(World *w, Object *o)
  202. {
  203.     List *l;
  204.  
  205.     l = scan_list(w->objects, o, find_node);
  206.     if (l == NULL)
  207.         return FALSE;
  208.     else
  209.         {
  210.         remove_node(l);
  211.         return TRUE;
  212.         }
  213. }
  214.  
  215.  
  216.  
  217. /* Derive a view from an object.  Assume that some fields of the view struct
  218. **   have already been filled in:  view_plane_size, view_arc, and others that
  219. **   cannot be determined from the object.
  220. */
  221. void object_view(Object *o, View *v)
  222. {
  223.      v->x = FLOAT_TO_FIXED(o->x);
  224.      v->y = FLOAT_TO_FIXED(o->y);
  225.      v->height = FLOAT_TO_FIXED(o->z + o->height);
  226.      v->angle = FLOAT_TO_FIXED(o->angle);
  227. }
  228.  
  229.  
  230.  
  231. void AdvanceFrame(Object *o)
  232. {
  233.     o->cur_image = (o->cur_image + 1) % o->num_images;
  234. }
  235.  
  236.  
  237.  
  238. Boolean AddFrame(Object *o, char *TextureName)
  239. {
  240.     if (o->num_images >= MAX_IMAGES)
  241.         return FALSE;
  242.         
  243.     o->image[o->num_images++] = read_texture_file(TextureName);
  244.     return TRUE;
  245. }
  246.